﻿using HardcoreGame.Common.Systems;
using HardcoreGame.Content.Items.Bosses.PumpkinBoy;
using HardcoreGame.Content.Items.Weapons.Sets.Heavy;
using Microsoft.Xna.Framework;
using System;
using Terraria;
using Terraria.Audio;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Terraria.ID;
using Terraria.ModLoader;

namespace HardcoreGame.Content.NPCs.Bosses.PB
{
    [AutoloadBossHead]
    public class PumpkinBoy : ModNPC
    {
        private enum AIState
        {
            Spawning,
            Float,
            FireCandy,
            DropBombs,
            SpinAttack,
            ChargeAttack,
        }
        private AIState CurrentState
        {
            get => (AIState)NPC.ai[0];
            set => NPC.ai[0] = (float)value;
        }
        private int StateTimer
        {
            get => (int)NPC.ai[1];
            set => NPC.ai[1] = value;
        }
        private int AttackCounter
        {
            get => (int)NPC.ai[2];
            set => NPC.ai[2] = value;
        }
        private int TargetPlayer
        {
            get => (int)NPC.ai[3];
            set => NPC.ai[3] = value;
        }
        public override void SetStaticDefaults()
        {
            Main.npcFrameCount[Type] = 16;
        }
        public override void SetDefaults()
        {
            NPC.width = 96;
            NPC.height = 63;
            NPC.damage = 24;
            NPC.defense = 3;
            NPC.lifeMax = 1700;
            NPC.value = 60000f;
            NPC.knockBackResist = 0f;
            NPC.aiStyle = -1;
            AnimationType = 62;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.boss = true;
            NPC.lavaImmune = true;
            NPC.noGravity = true;
            NPC.noTileCollide = true;
            AIType = -1;
            if (!Main.dedServ)
            {
                Music = MusicLoader.GetMusicSlot(Mod, "Assets/Music/Bosses/PumpkinBoy");
            }
        }
        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            bestiaryEntry.Info.AddRange([
                BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Times.NightTime,
                new FlavorTextBestiaryInfoElement("Mods.HardcoreGame.NPCs.PumpkinBoy.Bestiary")
            ]);
        }
        public override void AI()
        {
            if (TargetPlayer < 0 || !Main.player[TargetPlayer].active || Main.player[TargetPlayer].dead)
            {
                TargetPlayer = NPC.FindClosestPlayer();
                if (TargetPlayer < 0)
                {
                    NPC.TargetClosest();
                    TargetPlayer = NPC.target;
                }
            }

            Player target = Main.player[TargetPlayer];
            if (!target.active || target.dead)
            {
                NPC.velocity.Y -= 0.1f;
                NPC.alpha += 5;
                if (NPC.alpha >= 255)
                {
                    NPC.active = false;
                }
                return;
            }
            NPC.spriteDirection = NPC.direction = target.Center.X > NPC.Center.X ? 1 : -1;
            switch (CurrentState)
            {
                case AIState.Spawning:
                    HandleSpawningState(target);
                    break;
                case AIState.Float:
                    HandleFloatState(target);
                    break;
                case AIState.FireCandy:
                    HandleFireCandyState(target);
                    break;
                case AIState.DropBombs:
                    HandleDropBombsState(target);
                    break;
                case AIState.SpinAttack:
                    HandleSpinAttackState(target);
                    break;
                case AIState.ChargeAttack:
                    HandleChargeAttackState(target);
                    break;
            }
            StateTimer++;
        }
        private void HandleSpawningState(Player target)
        {
            ArgumentNullException.ThrowIfNull(target);
            if (StateTimer < 60)
            {
                NPC.alpha = 255 - StateTimer * 4;
                NPC.velocity.Y = -2f;
            }
            else
            {
                CurrentState = AIState.Float;
                StateTimer = 0;
                SoundEngine.PlaySound(SoundID.ForceRoar, NPC.Center);
            }
        }
        private void HandleChargeAttackState(Player target)
        {
            if (StateTimer == 0)
            {
                SoundEngine.PlaySound(SoundID.Item24, NPC.Center);
                NPC.velocity = Vector2.Zero;
                for (int i = 0; i < 20; i++)
                {
                    Vector2 offset = Vector2.UnitX.RotatedBy(MathHelper.TwoPi * i / 20) * 30f;
                    Dust.NewDust(NPC.Center + offset, 10, 10, DustID.Pumpkin,
                        0f, 0f, 100, default, 1.5f);
                }
            }
            else if (StateTimer < 30)
            {
                NPC.alpha = 100 + (int)(155 * (1f - StateTimer / 30f));
                Vector2 direction = target.Center - NPC.Center;
                NPC.rotation = direction.ToRotation() + (NPC.direction < 0 ? MathHelper.Pi : 0);
                if (StateTimer == 15)
                {
                    SoundEngine.PlaySound(SoundID.ForceRoar with { Volume = 0.8f, Pitch = 0.2f }, NPC.Center);
                }
            }
            else if (StateTimer < 150)
            {
                NPC.alpha = 50;
                Vector2 direction = target.Center - NPC.Center;
                direction.Normalize();
                if (StateTimer < 60)
                {
                    NPC.velocity = Vector2.Lerp(NPC.velocity, direction * 12f, 0.2f);
                }
                else
                {
                    NPC.velocity = direction * 12f;
                }
                NPC.rotation = NPC.velocity.ToRotation() + (NPC.direction < 0 ? MathHelper.Pi : 0);
                if (StateTimer % 2 == 0)
                {
                    Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Torch,
                        -NPC.velocity.X * 0.3f, -NPC.velocity.Y * 0.3f, 100, Color.Orange, 1.2f);
                }
            }
            else
            {
                NPC.velocity *= 0.9f;
                NPC.alpha += 5;

                if (StateTimer > 180)
                {
                    CurrentState = AIState.Float;
                    StateTimer = 0;
                    NPC.rotation = 0f;
                    NPC.alpha = 0;
                }
            }
        }
        private void HandleFloatState(Player target)
        {
            Vector2 targetPos = target.Center + new Vector2(0, -150);
            Vector2 direction = targetPos - NPC.Center;
            float distance = direction.Length();

            if (distance > 10)
            {
                direction.Normalize();
                NPC.velocity = direction * Math.Min(distance * 0.05f, 6f);
            }
            else
            {
                NPC.velocity *= 0.9f;
            }
            if (StateTimer > 120)
            {
                StateTimer = 0;

                switch (AttackCounter % 5)
                {
                    case 0:
                        CurrentState = AIState.SpinAttack;
                        break;
                    case 1:
                        CurrentState = AIState.ChargeAttack;
                        break;
                    case 2:
                        CurrentState = AIState.DropBombs;
                        break;
                    case 3:
                        CurrentState = AIState.FireCandy;
                        break;
                    case 4:
                        CurrentState = AIState.SpinAttack;
                        break;
                }

                AttackCounter++;
            }
        }

        private void HandleFireCandyState(Player target)
        {
            if (StateTimer == 0)
            {
                SoundEngine.PlaySound(SoundID.Item1, NPC.Center);
            }

            if (StateTimer < 60)
            {
                if (StateTimer % 10 == 0)
                {
                    Vector2 velocity = Vector2.Normalize(target.Center - NPC.Center) * 5f;

                    Projectile.NewProjectile(NPC.GetSource_FromAI(),
                        NPC.Center, velocity, ModContent.ProjectileType<CandyProjectile>(),
                        15, 1f, Main.myPlayer);
                }
            }
            else
            {
                CurrentState = AIState.Float;
                StateTimer = 0;
            }
        }

        private void HandleDropBombsState(Player target)
        {
            ArgumentNullException.ThrowIfNull(target);
            if (StateTimer == 0)
            {
                SoundEngine.PlaySound(SoundID.Item10, NPC.Center);
            }
            if (StateTimer < 90)
            {
                if (StateTimer % 20 == 0)
                {
                    Vector2 velocity = new(Main.rand.NextFloat(-2f, 2f), 5f);
                    Projectile.NewProjectile(NPC.GetSource_FromAI(),
                        NPC.Center, velocity, ModContent.ProjectileType<PumpkinBomb>(),
                        20, 1f, Main.myPlayer);
                }
            }
            else
            {
                CurrentState = AIState.Float;
                StateTimer = 0;
            }
        }
        private void HandleSpinAttackState(Player target)
        {
            if (StateTimer == 0)
            {
                SoundEngine.PlaySound(SoundID.Item9, NPC.Center);
                NPC.rotation = 0f;
            }
            float spinSpeed = 0.1f + StateTimer * 0.001f;
            NPC.rotation += spinSpeed * NPC.direction;
            Vector2 direction = target.Center - NPC.Center;
            direction.Normalize();
            NPC.velocity = direction * 4f;
            if (StateTimer % 5 == 0)
            {
                for (int i = 0; i < 4; i++)
                {
                    Vector2 offset = Vector2.UnitX.RotatedBy(NPC.rotation + i * MathHelper.PiOver2) * 40f;
                    Dust.NewDust(NPC.Center + offset, 10, 10, DustID.Torch,
                        0f, 0f, 100, Color.Orange, 1.2f);
                }
            }

            if (StateTimer > 180)
            {
                CurrentState = AIState.Float;
                StateTimer = 0;
                NPC.rotation = 0f;
            }
        }
        public override void ModifyHitByProjectile(Projectile projectile, ref NPC.HitModifiers modifiers)
        {
            if (CurrentState == AIState.SpinAttack)
            {
                modifiers.SourceDamage *= 0.7f;
            }
        }
        public override void OnKill()
        {
            NPC.SetEventFlagCleared(ref DownedBossSystem.downedPumpkinBoy, -1);
        }
        public override void BossLoot(ref string name, ref int potionType)
        {
            potionType = ItemID.LesserHealingPotion;
        }
        public override bool CanHitPlayer(Player target, ref int cooldownSlot)
        {
            cooldownSlot = ImmunityCooldownID.Bosses;
            return true;
        }
        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ModContent.ItemType<PumpkinBoyTrophy>(), 10));
            LeadingConditionRule notExpertRule = new(new Conditions.NotExpert());
            notExpertRule.OnSuccess(ItemDropRule.Common(ModContent.ItemType<PumpkingMask>(), 7));
            notExpertRule.OnSuccess(ItemDropRule.Common(ModContent.ItemType<Reaper>(), 2, 1));
            notExpertRule.OnSuccess(ItemDropRule.Common(ModContent.ItemType<Items.Bosses.PumpkinBoy.PumpkinBomb>(), 2, 50, 75));
            npcLoot.Add(notExpertRule);
            npcLoot.Add(ItemDropRule.BossBag(ModContent.ItemType<PumpkingBag>()));
            npcLoot.Add(ItemDropRule.MasterModeCommonDrop(ModContent.ItemType<PumpkingBoyRelic>()));

        }
    }
}